`include "PRV564Config.v"
`include "PRV564Define.v"
//       Dispatch Buffer 派遣缓冲器，为了分割ID和执行级，解决时序反压.
module DispBuffer(
    input wire              DBi_CLK,
    input wire              DBi_ARST,
    input wire              DBi_Flush,
//---------------输入------------------
    input wire              DBi_MSC_valid,
    input wire  [`XLEN-1:0] DBi_INFO_pc,
    input wire  [1:0]       DBi_INFO_priv,
    input wire  [7:0]       DBi_INFO_ITAG,
    input wire              DBi_INFO_unpage,
    input wire  [7:0]       DBi_Opcode,
    input wire  [3:0]       DBi_OpSize,
    input wire  [1:0]       DBi_OPInfo,
    input wire  [`XLEN-1:0] DBi_DATA_ds1,
    input wire  [`XLEN-1:0] DBi_DATA_ds2,          
    output reg              DBo_ready,
//------------Buffer输出---------------
    output reg              DBo_MSC_valid,
    output reg  [`XLEN-1:0] DBo_INFO_pc,
    output reg  [1:0]       DBo_INFO_priv,
    output reg  [7:0]       DBo_INFO_ITAG,
    output reg              DBo_INFO_unpage,
    output reg  [7:0]       DBo_Opcode,
    output reg  [3:0]       DBo_OpSize,
    output reg  [1:0]       DBo_OPInfo,
    output reg  [`XLEN-1:0] DBo_DATA_ds1,
    output reg  [`XLEN-1:0] DBo_DATA_ds2,          
    input wire              DBi_FC_ready
);
    reg  rd_pointer, wr_pointer;            //读写指针
//----------------------两个表项做缓冲区--------------------------
    reg              Buffer0_MSC_valid,     Buffer1_MSC_valid;
    reg  [`XLEN-1:0] Buffer0_INFO_pc,       Buffer1_INFO_pc;
    reg  [1:0]       Buffer0_INFO_priv,     Buffer1_INFO_priv;
    reg  [7:0]       Buffer0_INFO_ITAG,     Buffer1_INFO_ITAG;
    reg              Buffer0_INFO_unpage,   Buffer1_INFO_unpage;
    reg  [7:0]       Buffer0_Opcode,        Buffer1_Opcode;
    reg  [3:0]       Buffer0_OpSize,        Buffer1_OpSize;
    reg  [1:0]       Buffer0_OpInfo,        Buffer1_OpInfo;
    reg  [`XLEN-1:0] Buffer0_DATA_ds1,      Buffer1_DATA_ds1;
    reg  [`XLEN-1:0] Buffer0_DATA_ds2,      Buffer1_DATA_ds2;

always@(posedge DBi_CLK or posedge DBi_ARST)begin
    if(DBi_ARST)begin
        rd_pointer  <= 1'b0;
    end
    else if(DBi_Flush)begin
        rd_pointer  <= 1'b0;
    end
    else if(DBi_FC_ready)begin
        rd_pointer  <= rd_pointer + 1'b1;       //指针+1
    end
end
always@(posedge DBi_CLK or posedge DBi_ARST)begin
    if(DBi_ARST)begin
        wr_pointer <= 1'b0;
    end
    else if(DBi_Flush)begin
        wr_pointer <= 1'b0;
    end
    else begin
        case(wr_pointer)
            1'b0 : if(!Buffer0_MSC_valid & DBi_MSC_valid)begin      //如果Buffer0是空项，则写入成功，跳到下一状态
                        wr_pointer <= 1'b1;
                    end
            1'b1 :  if(!Buffer1_MSC_valid & DBi_MSC_valid)begin     
                        wr_pointer <= 1'b0;
                    end
        endcase
    end
end
//--------------------Buffer0----------------------
always@(posedge DBi_CLK or posedge DBi_ARST)begin
    if(DBi_ARST)begin
        Buffer0_MSC_valid <= 1'b0;
    end
    else if(DBi_Flush)begin
        Buffer0_MSC_valid <= 1'b0;
    end
    else begin
        case(Buffer0_MSC_valid)
            1'b0 :  if(!wr_pointer & DBi_MSC_valid)begin    //当前是空表项，且写入使能
                        Buffer0_MSC_valid <= 1'b1;
                        Buffer0_INFO_pc   <= DBi_INFO_pc;
                        Buffer0_INFO_priv <= DBi_INFO_priv;
                        Buffer0_INFO_ITAG <= DBi_INFO_ITAG;
                        Buffer0_INFO_unpage<=DBi_INFO_unpage;
                        Buffer0_Opcode    <= DBi_Opcode;
                        Buffer0_OpSize    <= DBi_OpSize;
                        Buffer0_OpInfo    <= DBi_OPInfo;
                        Buffer0_DATA_ds1  <= DBi_DATA_ds1;
                        Buffer0_DATA_ds2  <= DBi_DATA_ds2;
                    end
            1'b1 :  if(!rd_pointer & DBi_FC_ready)begin     //当前表项被读出
                        Buffer0_MSC_valid <= 1'b0;
                    end
        endcase
    end
end
//-----------------------Buffer1------------------------
always@(posedge DBi_CLK or posedge DBi_ARST)begin
    if(DBi_ARST)begin
        Buffer1_MSC_valid <= 1'b0;
    end
    else if(DBi_Flush)begin
        Buffer1_MSC_valid <= 1'b0;
    end
    else begin
        case(Buffer1_MSC_valid)
            1'b0 :  if(wr_pointer & DBi_MSC_valid)begin    //当前是空表项，且写入使能
                        Buffer1_MSC_valid <= 1'b1;
                        Buffer1_INFO_pc   <= DBi_INFO_pc;
                        Buffer1_INFO_priv <= DBi_INFO_priv;
                        Buffer1_INFO_ITAG <= DBi_INFO_ITAG;
                        Buffer1_INFO_unpage<=DBi_INFO_unpage;
                        Buffer1_Opcode    <= DBi_Opcode;
                        Buffer1_OpSize    <= DBi_OpSize;
                        Buffer1_OpInfo    <= DBi_OPInfo;
                        Buffer1_DATA_ds1  <= DBi_DATA_ds1;
                        Buffer1_DATA_ds2  <= DBi_DATA_ds2;
                    end
            1'b1 :  if(rd_pointer & DBi_FC_ready)begin     //当前表项被读出
                        Buffer1_MSC_valid <= 1'b0;
                    end
        endcase
    end
end
//----------------------output mux-----------------------
always@(*)begin
    DBo_MSC_valid   = rd_pointer ? Buffer1_MSC_valid : Buffer0_MSC_valid;
    DBo_INFO_pc     = rd_pointer ? Buffer1_INFO_pc   : Buffer0_INFO_pc;
    DBo_INFO_priv   = rd_pointer ? Buffer1_INFO_priv : Buffer0_INFO_priv;
    DBo_INFO_ITAG   = rd_pointer ? Buffer1_INFO_ITAG : Buffer0_INFO_ITAG;
    DBo_INFO_unpage = rd_pointer ? Buffer1_INFO_unpage:Buffer0_INFO_unpage;
    DBo_Opcode      = rd_pointer ? Buffer1_Opcode    : Buffer0_Opcode;
    DBo_OpSize      = rd_pointer ? Buffer1_OpSize    : Buffer0_OpSize;
    DBo_OPInfo      = rd_pointer ? Buffer1_OpInfo    : Buffer0_OpInfo;
    DBo_DATA_ds1    = rd_pointer ? Buffer1_DATA_ds1  : Buffer0_DATA_ds1;
    DBo_DATA_ds2    = rd_pointer ? Buffer1_DATA_ds2  : Buffer0_DATA_ds2;
end
//--------------------与前级的握手信号----------------------
always@(*)begin
    if(Buffer0_MSC_valid & Buffer1_MSC_valid)begin
        DBo_ready = 1'b0;
    end
    else begin
        DBo_ready = 1'b1;
    end
end
endmodule

